#include "SetAccessorBuilder.h"
#include "ScriptCompiler/ASTBuilder/SentenceBlockBuilder.h"
#include "ScriptCompiler/ASTBuilder/ExpressionBuilder.h"
#include "ScriptCompiler/ASTBuilder/TypeBuilder.h"
#include "ScriptCompiler/ScriptFileContext.h"
#include "ScriptCompiler/AST/SetAccessorNode.h"

CSetAccessorBuilder::CSetAccessorBuilder(std::shared_ptr<CScriptFileContext> InContext)
{
    Context = InContext;
    Result = std::make_shared<CSetAccessorNode>(Context);
}

bool CSetAccessorBuilder::ReadCurentToken()
{
    //check and skip 'set'
    if (Context->GetCurrentToken()->Type == EScriptTokenType::Set)
    {
        Context->CurrentTokenIndex++; //skip 'set'
        Result->SetKeyword = Context->GetCurrentToken();
    }
    else if(Context->GetCurrentToken()->Type == EScriptTokenType::Init)
    {
        Context->CurrentTokenIndex++; //skip 'init'
        Result->InitKeyword = Context->GetCurrentToken();
    }
    else
    {
        Context->RaiseError(10117,Context->GetCurrentToken(), U"Expected set/init keyword");
        return false;
    }




    //check and skip '{' or '=>'
    {
        auto Token = Context->GetCurrentToken();
        if (Token->Type == EScriptTokenType::LeftBrace)
        {
            Context->CurrentTokenIndex++; //skip '{'

            //find '}'
            auto RightBraceIndex = FindPairedBrace(Context);
            if (!RightBraceIndex)
            {
                //raise error
                Context->RaiseError(10166,Token,U"cant find paired '}'");
                return false;
            }

            auto SentenceBlockBuilder = std::make_shared<CSentenceBlockBuilder>(Context,RightBraceIndex.GetValue());
            if (!SentenceBlockBuilder->ReadCurentToken())
            {
                return false;
            }
            Result->Content = SentenceBlockBuilder->Result;

            //skip }
            assert(Context->CurrentTokenIndex==RightBraceIndex.GetValue());
            Context->CurrentTokenIndex++;
            return true; //finished;
          

        }
        else if (Token->Type == EScriptTokenType::LambdaOperator)
        {
            Context->CurrentTokenIndex++; //skip '=>'

            //find ';'
            auto SemiColonIndex = FindNextToken(EScriptTokenType::Semicolon,Context);
            if(!SemiColonIndex)
            {
                Context->RaiseError(10167,Context->GetCurrentToken(),U"Expected ';' at end of lambda function");
                return false;
            }

            auto LambdaBuilder = std::make_shared<CSentenceBlockBuilder>(Context,SemiColonIndex.GetValue());
            if (!LambdaBuilder->ReadCurentToken())
            {
                return false;
            }
            Result-> LambdaContent = LambdaBuilder->Result;

            //skip ;
            assert(Context->GetCurrentToken()->Type==EScriptTokenType::Semicolon);
            Context->CurrentTokenIndex++;

            return true; //finished;
        }
        else
        {
            Context->RaiseError(10119,Token,U"Expected '{' or '=>' after 'set' keyword");
            return false;
        }


    }
}